//============================================================================
// Name        : player_region.cpp
// Author      : dfoelber
//============================================================================

// INCLUDES //
#include "player_region.h"
#include "render_manager.h"
#include "image_manager.h"
#include "graphics/graphics.h"
#include "draw/SDL_draw.h"
#include <iostream>
#include <sstream>
//////////////

using namespace std;

/**
* Constructor
**/
PlayerRegion::PlayerRegion() :
	showDeck(false)
{
	currentDeck = playerDeck = totalDeck = 0;
	mainDeck = new Deck();
	discardDeck = new Deck();
	
	Surface* nameSurface = ImageManager::GetManager()->CreateImage(0,0);
	name = new Object(nameSurface, OBJECT_ID_NONE, true);
	name->GetPath()->SetPosition(0,0);
	
	Surface* deckSurface = ImageManager::GetManager()->CreateImage(0,0);
	deck = new Object(deckSurface, OBJECT_ID_NONE, true);
	deck->GetPath()->SetPosition(0,0);
}

/**
* Destructor
**/
PlayerRegion::~PlayerRegion()
{
	if (name)
	{
		delete name;
		name = NULL;
	}
	
	if (deck)
	{
		delete deck;
		deck = NULL;
	}
	
	if (mainDeck)
	{
		delete mainDeck;
		mainDeck = NULL;
	}
	
	if (discardDeck)
	{
		delete discardDeck;
		discardDeck = NULL;
	}
}

/**
* Sets the region's boundary.
* 
* Overridden from Region.
* 
* @param x The boundary's X coordinate
* @param y The boundary's Y coordinate
* @param width The boundary's width
* @param height The boundary's height
**/
void PlayerRegion::SetBoundary( int x, int y, int width, int height )
{
	Surface* nameSurface = ImageManager::GetManager()->CreateImage(width,height / 2);
	ImageManager::GetManager()->GetImage(IMAGE_PLAYER_BACKGROUND)->Apply(nameSurface, 0, 0);
	name->GetPath()->SetPosition(x,y);
	name->SetSurface(nameSurface, true);
	
	Color black;
	black.r = black.g = black.b = 0;
	Surface* deckSurface = ImageManager::GetManager()->CreateImage(width - BAR_LEFT_INDENT - BAR_RIGHT_INDENT, BAR_HEIGHT);
	deck->GetPath()->SetPosition(x + BAR_LEFT_INDENT,y + height - deckSurface->GetHeight() - 2);
	Draw_FillRect(deckSurface->GetSurface(), 0, 0, deckSurface->GetWidth(), deckSurface->GetHeight(), 0);
	deck->SetSurface(deckSurface, true);
}

/**
* Notify the region of an event.
* 
* Overridden from Region.
* 
* @param event The event that happened
* @return If the region used the event
**/
bool PlayerRegion::ProcessEvent( SDL_Event event )
{
	if( event.type == SDL_MOUSEMOTION )
	{
		if( deck &&
			event.button.x >= deck->GetPath()->GetX() && 
			event.button.x <= deck->GetPath()->GetX() + deck->GetPath()->GetWidth() && 
			event.button.y >= deck->GetPath()->GetY() && 
			event.button.y <= deck->GetPath()->GetY() + deck->GetPath()->GetHeight() )
		{
			showDeck = true;
		}
		else showDeck = false;
	}
	
	return Region::ProcessEvent( event );
}

/**
* Notifies of time passing.
* 
* Overridden from Region.
* 
* @param The amount of time, in milliseconds, that passed since the last call
**/
void PlayerRegion::TimePassed( int ms )
{
	// Deck Bar
	bool repaint = false;
	if( currentDeck < GetPercentDeck() )
	{
		currentDeck += (double)ms / 20.0;
		if( currentDeck > 100 )
			currentDeck = 100;
		repaint = true;
	}
	if( currentDeck > GetPercentDeck() )
	{
		currentDeck -= (double)ms / 20.0;
		if( currentDeck < 0 )
			currentDeck = 0;
		repaint = true;
	}
	
	if( repaint )
	{
		Color black;
		black.r = black.g = black.b = 0;
		SDL_Rect rect;
		rect.x = 0; rect.y = 0; rect.w = deck->GetPath()->GetWidth(); rect.h = deck->GetPath()->GetHeight();
		Draw_FillRect(deck->GetSurface()->GetSurface(), 0, 0, deck->GetPath()->GetWidth(), deck->GetPath()->GetHeight(), 0);

		double width = deck->GetPath()->GetWidth() * (currentDeck / 100);
		ImageManager::GetManager()->GetImage(IMAGE_PLAYER_DECK_SIZE)->Apply(deck->GetSurface(),
				ImageManager::GetManager()->GetImage(IMAGE_PLAYER_DECK_SIZE)->GetWidth() - (int)width,
				0,
				(int)width,
				deck->GetSurface()->GetWidth(),
				0,
				0);
	}
}

/**
* Renders the objects on the background
* 
* Overridden from Region.
**/
void PlayerRegion::Render()
{
	if( showDeck )
	{
		FontCustomRender* render = new FontCustomRender();
		Color color;
		color.r = color.g = color.b = 255;
		render->font = FONT_CICLE_FINA;
		render->color = color;
		ostringstream oss;
		oss << playerDeck << " / " << totalDeck;
		render->str = oss.str();
		render->size = FONT_SIZE_SMALL;
		render->x = deck->GetPath()->GetX();
		render->y = deck->GetPath()->GetY();
		render->width = deck->GetPath()->GetWidth();
		render->height = deck->GetPath()->GetHeight();
		render->alignment = ALIGNMENT_TOP | ALIGNMENT_MIDDLE;
		RenderManager::GetManager()->AddCustomRender(render);
	}
}

/*
* Sets the player's name.
* 
* @param name The new player name
**/
void PlayerRegion::SetPlayerName( string name )
{
	ImageManager::GetManager()->GetImage(IMAGE_PLAYER_BACKGROUND)->Apply(this->name->GetSurface(), 0, 0);
		
	Color c;
	c.b = c.g = c.r = 0;
	Graphics::GetGraphics()->DrawFont(this->name->GetSurface(), name, FONT_DEJA_VU_SANS, FONT_SIZE_NORMAL, c, 5, 5, 255);
}

/*
* Calculates the player's deck size as a percentage.
* 
* @return The player's deck size.
**/
int PlayerRegion::GetPercentDeck()
{
	if( totalDeck == 0 )
		return 0;
	
	else return (int)(( (double)playerDeck / (double)totalDeck ) * 100);
}

/*
* Loads an initial set of cards into the deck.
* 
* @param cards The cards to add.
**/
void PlayerRegion::LoadCards(vector<CardInfo*> cards)
{
	totalDeck = cards.size();
	mainDeck->Add(cards);
	mainDeck->Shuffle();
	
	playerDeck = mainDeck->GetSize();
}

/*
* Pops the top card from the deck and returns it.
* 
* @return The top card.
**/
Card* PlayerRegion::PopCard()
{
	if( mainDeck->GetSize() == 0 )
	{
		while( discardDeck->GetSize() > 0 )
		{
			mainDeck->Add(discardDeck->Remove());
		}
		
		mainDeck->Shuffle();
	}
	
	if( mainDeck->GetSize() == 0 )
	{
		playerDeck = 0;
		return NULL;
	}
	else
	{
		Card* card = new Card(mainDeck->Remove());
		
		playerDeck = mainDeck->GetSize();
		
		return card;
	}
}
